<?php

namespace App\Services;

use App\Jobs\ExpireRoomJob;
use App\Models\Room;
use App\Models\RoomMember;
use App\Models\Menu;
use App\Repositories\RoomRepository;
use App\Exceptions\BusinessException;
use App\Services\CacheService;
use App\Services\LogService;
use Illuminate\Support\Facades\DB;

class RoomService
{
    protected $roomRepository;
    protected $cacheService;
    protected $logService;

    public function __construct(RoomRepository $roomRepository, CacheService $cacheService, LogService $logService)
    {
        $this->roomRepository = $roomRepository;
        $this->cacheService = $cacheService;
        $this->logService = $logService;
    }

    /**
     * 创建房间
     */
    public function createRoom(array $data, int $creatorId): Room
    {
        DB::beginTransaction();
        
        try {
            $roomData = [
                'room_id' => Room::generateRoomId(),
                'title' => $data['title'],
                'type' => $data['type'],
                'creator_id' => $creatorId,
                'menu_source' => $data['menuSource'] ?? 'default',
                'settings' => $data['settings'] ?? [
                    'allowParticipantAdd' => true,
                    'allowParticipantSuggest' => true,
                    'showUserFavorites' => true,
                ],
                'expires_at' => $data['type'] === 'temporary' ? now()->addDay() : null,
            ];

            $room = $this->roomRepository->create($roomData);

            // 根据菜单来源处理菜单
            if ($room->menu_source === 'default') {
                // 创建新菜单并复制默认菜品
                $menu = Menu::create([
                    'name' => $room->title . '的菜单',
                    'description' => '基于默认菜单创建的菜单',
                    'creator_id' => $room->creator_id,
                    'source_type' => 'default',
                    'source_id' => null,
                    'is_public' => false,
                    'is_template' => false,
                ]);

                $room->update(['menu_id' => $menu->id]);

                $dishService = app(\App\Services\DishService::class);
                $dishService->initializeMenuDishes($menu);
            } elseif ($room->menu_source === 'custom' && isset($data['menu_id'])) {
                // 直接关联现有菜单
                $menu = Menu::find($data['menu_id']);
                if ($menu && ($menu->creator_id === $room->creator_id || $menu->is_public)) {
                    $room->update(['menu_id' => $menu->id]);
                }
            }

            // 创建者自动加入房间
            RoomMember::create([
                'room_id' => $room->id,
                'user_id' => $creatorId,
                'role' => 'creator',
                'joined_at' => now(),
                'last_active_at' => now(),
            ]);

            DB::commit();

            // 缓存房间信息
            $this->cacheService->putRoom($room->room_id, $room, CacheService::TTL_MEDIUM);

            // 记录创建房间活动
            $this->logService->logRoomActivity('创建房间', $room, [
                'creator_id' => $creatorId,
                'room_type' => $room->type,
                'menu_source' => $room->menu_source,
            ]);

            // 如果是临时房间，安排过期任务
            if ($room->type === 'temporary' && $room->expires_at) {
                $delayMinutes = now()->diffInMinutes($room->expires_at);
                if ($delayMinutes > 0) {
                    ExpireRoomJob::dispatch($room->id)->delay(now()->addMinutes($delayMinutes));
                }
            }

            return $room;

        } catch (\Exception $e) {
            DB::rollBack();
            throw new BusinessException('创建房间失败：' . $e->getMessage());
        }
    }

    /**
     * 加入房间
     */
    public function joinRoom(string $roomId, int $userId): Room
    {
        $room = $this->roomRepository->findByRoomId($roomId);
        
        if (!$room) {
            throw new BusinessException('房间不存在', 10001);
        }

        if ($room->status !== 'active') {
            throw new BusinessException('房间已关闭', 10002);
        }

        if ($this->roomRepository->isExpired($room)) {
            throw new BusinessException('房间已过期', 10003);
        }

        if ($this->isUserInRoom($room->id, $userId)) {
            throw new BusinessException('您已在此房间中', 10005);
        }

        if ($this->getRoomMemberCount($room->id) >= $room->max_participants) {
            throw new BusinessException('房间人数已达上限', 10006);
        }

        // 加入房间
        RoomMember::create([
            'room_id' => $room->id,
            'user_id' => $userId,
            'role' => 'member',
            'joined_at' => now(),
            'last_active_at' => now(),
        ]);

        // 更新房间最后活动时间
        $this->roomRepository->updateLastActivity($room->id);

        return $room;
    }

    /**
     * 获取房间信息
     */
    public function getRoomInfo(string $roomId, int $userId): Room
    {
        $room = $this->roomRepository->findByRoomId($roomId);
        
        if (!$room) {
            throw new BusinessException('房间不存在', 10001);
        }

        if (!$this->isUserInRoom($room->id, $userId)) {
            throw new BusinessException('无权限访问房间', 10004);
        }

        return $room;
    }

    /**
     * 更新房间设置
     */
    public function updateRoomSettings(string $roomId, array $settings, int $userId): void
    {
        $room = $this->roomRepository->findByRoomId($roomId);
        
        if (!$room) {
            throw new BusinessException('房间不存在', 10001);
        }

        if ($room->creator_id !== $userId) {
            throw new BusinessException('无权限修改房间设置', 10004);
        }

        $this->roomRepository->update($room->id, ['settings' => $settings]);
    }

    /**
     * 关闭房间
     */
    public function closeRoom(string $roomId, int $userId): void
    {
        $room = $this->roomRepository->findByRoomId($roomId);
        
        if (!$room) {
            throw new BusinessException('房间不存在', 10001);
        }

        if ($room->creator_id !== $userId) {
            throw new BusinessException('无权限关闭房间', 10004);
        }

        $this->roomRepository->update($room->id, ['status' => 'closed']);
    }

    /**
     * 检查用户是否在房间中
     */
    private function isUserInRoom(int $roomId, int $userId): bool
    {
        return RoomMember::where('room_id', $roomId)
            ->where('user_id', $userId)
            ->exists();
    }

    /**
     * 获取房间成员数量
     */
    private function getRoomMemberCount(int $roomId): int
    {
        return RoomMember::where('room_id', $roomId)->count();
    }

    /**
     * 获取房间成员
     */
    public function getRoomMembers(int $roomId): \Illuminate\Database\Eloquent\Collection
    {
        return RoomMember::where('room_id', $roomId)
            ->with('user')
            ->get();
    }

    /**
     * 检查用户权限
     */
    public function checkUserPermission(Room $room, int $userId, string $permission): bool
    {
        $member = RoomMember::where('room_id', $room->id)
            ->where('user_id', $userId)
            ->first();

        if (!$member) {
            return false;
        }

        switch ($permission) {
            case 'manage_room':
                return in_array($member->role, ['creator', 'admin']);
            case 'add_dishes':
                $settings = $room->settings ?? [];
                return $member->role === 'creator' || 
                       $member->role === 'admin' || 
                       ($settings['allowParticipantAdd'] ?? true);
            case 'suggest_dishes':
                $settings = $room->settings ?? [];
                return $member->role === 'creator' || 
                       $member->role === 'admin' || 
                       ($settings['allowParticipantSuggest'] ?? true);
            default:
                return false;
        }
    }

    /**
     * 获取用户房间列表
     */
    public function getUserRooms(int $userId, array $filters = []): array
    {
        $query = RoomMember::with(['room.creator', 'room.members'])
            ->where('user_id', $userId)
            ->where('is_active', true);

        // 房间类型筛选
        if (isset($filters['type']) && $filters['type'] !== 'all') {
            $query->whereHas('room', function ($q) use ($filters) {
                $q->where('type', $filters['type']);
            });
        }

        // 房间状态筛选
        if (isset($filters['status']) && $filters['status'] !== 'all') {
            $query->whereHas('room', function ($q) use ($filters) {
                $q->where('status', $filters['status']);
            });
        }

        // 排序：置顶的在前，然后按加入时间倒序
        $query->orderByRaw('is_pinned DESC, joined_at DESC');

        $limit = $filters['limit'] ?? 20;
        $offset = $filters['offset'] ?? 0;

        $total = $query->count();
        $roomMembers = $query->limit($limit)->offset($offset)->get();

        return [
            'rooms' => $this->formatRoomList($roomMembers),
            'pagination' => [
                'total' => $total,
                'limit' => $limit,
                'offset' => $offset,
                'has_more' => ($offset + $limit) < $total,
            ],
        ];
    }

    /**
     * 获取最近房间
     */
    public function getRecentRooms(int $userId, int $limit = 10, int $days = 7): array
    {
        $roomMembers = RoomMember::with(['room.creator', 'room.members'])
            ->where('user_id', $userId)
            ->where('is_active', true)
            ->whereHas('room', function ($q) {
                $q->where('status', 'active');
            })
            ->where('last_active_at', '>=', now()->subDays($days))
            ->orderBy('last_active_at', 'desc')
            ->limit($limit)
            ->get();

        return [
            'rooms' => $this->formatRoomList($roomMembers, true),
        ];
    }

    /**
     * 获取置顶房间
     */
    public function getPinnedRooms(int $userId): array
    {
        $roomMembers = RoomMember::with(['room.creator', 'room.members'])
            ->where('user_id', $userId)
            ->where('is_active', true)
            ->where('is_pinned', true)
            ->whereHas('room', function ($q) {
                $q->where('status', 'active');
            })
            ->orderBy('pin_order', 'desc')
            ->get();

        return [
            'rooms' => $this->formatRoomList($roomMembers),
        ];
    }

    /**
     * 设置房间置顶
     */
    public function pinRoom(int $userId, int $roomId): bool
    {
        $roomMember = RoomMember::where('user_id', $userId)
            ->where('room_id', $roomId)
            ->where('is_active', true)
            ->first();

        if (!$roomMember) {
            return false;
        }

        $roomMember->pin();
        return true;
    }

    /**
     * 取消房间置顶
     */
    public function unpinRoom(int $userId, int $roomId): bool
    {
        $roomMember = RoomMember::where('user_id', $userId)
            ->where('room_id', $roomId)
            ->where('is_active', true)
            ->first();

        if (!$roomMember) {
            return false;
        }

        $roomMember->unpin();
        return true;
    }

    /**
     * 更新房间访问时间
     */
    public function updateRoomVisit(int $userId, int $roomId): void
    {
        $roomMember = RoomMember::where('user_id', $userId)
            ->where('room_id', $roomId)
            ->where('is_active', true)
            ->first();

        if ($roomMember) {
            $roomMember->updateLastVisitedAt();
        }
    }

    /**
     * 格式化房间列表数据
     */
    private function formatRoomList(\Illuminate\Database\Eloquent\Collection $roomMembers, bool $includeTimeAgo = false): array
    {
        return $roomMembers->map(function ($roomMember) use ($includeTimeAgo) {
            $room = $roomMember->room;
            $creator = $room->creator;

            $data = [
                'id' => $room->id,
                'room_id' => $room->room_id,
                'title' => $room->title,
                'type' => $room->type,
                'status' => $room->status,
                'creator' => [
                    'id' => $creator->id,
                    'nickname' => $creator->nickname,
                    'avatar' => $creator->avatar,
                ],
                'members_count' => $room->members->where('is_active', true)->count(),
                'max_participants' => $room->max_participants,
                'current_round' => $room->current_round,
                'total_orders' => $room->total_orders,
                'last_activity_at' => $room->last_activity_at ? $room->last_activity_at->format('Y-m-d H:i:s') : null,
                'created_at' => $room->created_at->format('Y-m-d H:i:s'),
                'is_pinned' => $roomMember->is_pinned,
                'joined_at' => $roomMember->joined_at->format('Y-m-d H:i:s'),
            ];

            if ($includeTimeAgo) {
                $data['time_ago'] = $this->getTimeAgo($roomMember->last_visited_at);
            }

            if ($roomMember->is_pinned && $roomMember->pinned_at) {
                $data['pinned_at'] = $roomMember->pinned_at->format('Y-m-d H:i:s');
            }

            return $data;
        })->toArray();
    }

    /**
     * 获取相对时间显示
     */
    private function getTimeAgo($datetime): string
    {
        if (!$datetime) {
            return '未知';
        }

        $diff = now()->diffInMinutes($datetime);

        if ($diff < 1) {
            return '刚刚';
        } elseif ($diff < 60) {
            return $diff . '分钟前';
        } elseif ($diff < 1440) {
            return floor($diff / 60) . '小时前';
        } elseif ($diff < 10080) {
            return floor($diff / 1440) . '天前';
        } else {
            return $datetime->format('Y-m-d');
        }
    }

    /**
     * 获取菜单菜品
     */
    public function getMenuDishes(Menu $menu): \Illuminate\Database\Eloquent\Collection
    {
        $dishService = app(\App\Services\DishService::class);
        return $dishService->getMenuDishes($menu);
    }

    /**
     * 获取分类列表
     */
    public function getCategories(): array
    {
        $categories = \App\Models\Category::where('is_active', true)
            ->orderBy('sort_order', 'asc')
            ->get();

        $result = [
            [
                'id' => 'all',
                'name' => '全部',
                'slug' => 'all',
                'description' => '所有菜品'
            ]
        ];

        foreach ($categories as $category) {
            $result[] = [
                'id' => $category->id,
                'name' => $category->name,
                'slug' => $category->slug,
                'description' => $category->description,
            ];
        }

        return $result;
    }
}
